#if !defined(___OS_LIN)
#error Invalid OS
#endif

/*====================== Time ===========================================*/

xx TimeWait(N4 tmm)
{ N4 n=tmm/1000ul;
  if (n) while ((n=sleep(n)));
  usleep((tmm%1000ul)*1000ul);
}

/*====================== Exec ===========================================*/

#define ___EXE

N4 MemExe(Ptr mem,N4 len)
{ if (!mem && len) return (-1);
  if (mprotect(mem,len,PROT_READ|PROT_WRITE|PROT_EXEC))
    return (-1); else return (0);
}

/*====================== Module =========================================*/

#define ___LIB

N4 LibOpen(Str nam)
{ N4 id;
  if (!nam) return (-1);
  id=(N4)dlopen((CS)nam,RTLD_GLOBAL|RTLD_LAZY);
  if (!id) return (-1);
  return (id);
}

xx LibClose(N4 id)
{ if (id==-1) return;
  dlclose((Ptr)id);
}

Ptr AdrGet(N4 id,Str nam)
{ Ptr adr;
  if (!nam) return (NULL);
  adr=dlsym((Ptr)id,(CS)nam);
  return (adr);
}

xx AdrRel(N4 id,Ptr adr)
{
}

/*====================== Thread =========================================*/

#define ___THR
N1 isth=1;

N4 ThBeg(fFun fun,N4 par)
{ pthread_t id;

  if (!fun) return (-1);
  if (pthread_create(&id,NULL,(Ptr (*)(Ptr))fun,(Ptr)par))
    return (-1);
  if (!id)
  { fputs("Error: ThBeg: Zero\n",err);
    SysExit(-1);
  }

  return ((N4)id);
}

xx ThEnd(N4 id)
{ if (id==-1) return;
  pthread_kill((pthread_t)id,SIGTERM);
}

N4 ThId(xx)
{ return ((N4)pthread_self());
}

N4 ThLkGet(xx)
{ pthread_mutex_t *id;
  pthread_mutexattr_t attr;

  if (pthread_mutexattr_init(&attr)) return (-1);
  /*if (pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP)) return (-1);*/
  if (!(id=(pthread_mutex_t *)MemGet(sizeof(pthread_mutex_t)))) return (-1);
  if (pthread_mutex_init(id,&attr)) { MemRel((Ptr)id); return (-1); }

  return ((N4)id);
}

xx ThLkRel(N4 id)
{ if (id==-1) return;
  pthread_mutex_destroy((pthread_mutex_t *)id);
  MemRel((Ptr)id);
}

N4 ThLkBeg(N4 id)
{ if (pthread_mutex_lock((pthread_mutex_t *)id))
    return (-1); else return (0);
}

N4 ThLkEnd(N4 id)
{ if (pthread_mutex_unlock((pthread_mutex_t *)id))
    return (-1); else return (0);
}

/*-----------------------------------------------------------------------*/

N4 ThEvtGet(xx)
{ pthread_cond_t *id;
  pthread_condattr_t attr;

  if (pthread_condattr_init(&attr)) return (-1);
  if (!(id=(pthread_cond_t *)MemGet(sizeof(pthread_cond_t)))) return (-1);
  if (pthread_cond_init(id,&attr)) { MemRel((Ptr)id); return (-1); }

  return ((N4)id);
}

xx ThEvtRel(N4 id)
{ if (id==-1) return;
  pthread_cond_destroy((pthread_cond_t *)id);
  MemRel((Ptr)id);
}

N4 ThEvtSet(N4 id)
{ if (pthread_cond_signal((pthread_cond_t *)id))
    return (-1); else return (0);
};

N4 ThEvtNul(N4 id)
{ return (0);
};

xx ThEvtWait(N4 id,N4 lk,N4 tmm)
{ struct timeval tm1;
  struct timezone tz1;
  struct timespec tm2;

  if (tmm!=-1)
  { gettimeofday(&tm1,&tz1);
    tm2.tv_sec=tm1.tv_sec+tmm/1000;
    tm2.tv_nsec=tm1.tv_usec*1000ul+(tmm%1000)*1000ul*1000ul;
    pthread_cond_timedwait((pthread_cond_t *)id,(pthread_mutex_t *)lk,&tm2);
  } else pthread_cond_wait((pthread_cond_t *)id,(pthread_mutex_t *)lk);
};

/*=======================================================================*/
